package com.turing.post.util;

import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.net.Socket;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.naming.InitialContext;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import weblogic.logging.NonCatalogLogger;
import weblogic.workarea.PrimitiveContextFactory;
import weblogic.workarea.PropagationMode;
import weblogic.workarea.WorkContext;
import weblogic.workarea.WorkContextMap;

/**
 * 实用类
 * 
 * @author 图灵软件
 * @version 1.0
 * @since 2008.03.14
 */
public class PCPSUtil {

	/**
	 * @机构身份枚举1.发卡商，
	 */
	public final static Integer SysBranch_IssueCompany = 1;
	/**
	 * @机构身份枚举2.发卡商机构，
	 */
	public final static Integer SysBranch_IssueBranch = 2;
	/**
	 * @机构身份枚举3.销售商,
	 */
	public final static Integer SysBranch_SaleCompany = 3;
	/**
	 * @机构身份枚举4.销售商分支机构
	 */
	public final static Integer SysBranch_SaleBranch = 4;
	/**
	 * @机构身份枚举5.商户,
	 */
	public final static Integer SysBranch_Merchant = 5;
	/**
	 * @机构身份枚举6.商户分支机构
	 */
	public final static Integer SysBranch_MerchantBranch = 6;
	/**
	 * @机构身份枚举7.无法识别
	 */
	public final static Integer SysBranch_INVALID = 0;

	/**
	 * @业务执行判断SUCCESS
	 */
	public final static boolean SUCCESS = true;

	/**
	 * @业务执行判断FAILED
	 */
	public final static boolean FAILED = false;
	/**
	 * 缺省的汉字编码
	 */
	public final static String CHINESE_ENCODING = "GB18030";

	public final static String first_Blank = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
	/**
	 * 操作系统默认的换行符字节串
	 */
	public final static byte[] LINE_FEED_ = System
			.getProperty("line.separator").getBytes();;
	/**
	 * 缺省的小数格式化串
	 */
	public final static String DEFAULT_DECIMAL_FMT = "0.00";
	/**
	 * 缺省的整数格式化串
	 */
	public final static String DEFAULT_INTEGER_FMT = "0";
	/**
	 * 日期格式化串yyyyMMddHHmmss
	 */
	public final static String DEFAULT_DATE_FMT = "yyyyMMddHHmmss";
	/**
	 * 日期格式化串yyyyMMddHHmmss
	 */
	public final static String DEFAULT_DATE_FMT_yMdHms = "yyyy-MM-dd HH-mm-ss";
	/**
	 * 日期格式化串yyyyMMddHHmmss
	 */
	public final static String DEFAULT_TIMESTAMP_FMT = "yyyyMMddHHmmssSSS";

	/**
	 * 日期格式化串yyyy-MM-dd
	 */
	public final static String DEFAULT_DATE_YMD_FMT = "yyyy-MM-dd";

	/**
	 * 日期格式化串yyyyMMdd
	 */
	public final static String PACKED_DATE_YMD_FMT = "yyyyMMdd";

	private static NonCatalogLogger myLogger = new NonCatalogLogger(
			"MyApplication");

	/**
	 * 格式化指定的串按指定的长度--右补特定字符
	 * 
	 * @param value
	 *            待格式化的字符串
	 * @param fmtlen
	 *            格式化字节长度
	 * @param fill
	 *            填充的字符
	 * @return 格式化好的字节数组
	 */
	public static byte[] formatString(String value, int fmtlen, char fill)
			throws Exception {
		byte[] bu = value.trim().getBytes(CHINESE_ENCODING);
		byte[] bret = new byte[fmtlen];

		if (bu.length > fmtlen)
			throw new Exception("format [" + value + "] to " + fmtlen
					+ "bytes failed!");

		System.arraycopy(bu, 0, bret, 0, bu.length > fmtlen ? fmtlen
				: bu.length);
		// 不足部分填充空格
		for (int i = bu.length; i < fmtlen; i++)
			bret[i] = (byte) fill;
		return (bret);
	}

	/**
	 * 格式化指定的串按指定的长度--缺省右补空格
	 * 
	 * @param value
	 *            待格式化的字符串
	 * @param fmtlen
	 *            格式化字节长度
	 * @return 格式化好的字节数组
	 */
	public static byte[] formatString(String value, int fmtlen)
			throws Exception {
		return (formatString(value, fmtlen, ' '));
	}

	/**
	 * 获取当前时间前几天
	 * 
	 * @param c
	 * @param day
	 * @return
	 */
	public static String BeforeNowDate(Date d, int day) {
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		c.add(Calendar.DATE, day);
		c.getTime();
		return getPackedYMDString2(c.getTime());
	}

	/**
	 * 获取d日期开始N个月之后的日期
	 * 
	 * @param d
	 * @param month
	 * @return
	 */
	public static String BeforeNowMonth(Date d, int month) {
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		c.add(Calendar.MONTH, month);
		c.getTime();
		return getPackedYMDString2(c.getTime());
	}

	/**
	 * 格式化指定的串按指定的长度--缺省右补空格
	 * 
	 * @param value
	 *            待格式化的字符串
	 * @param fmtlen
	 *            格式化字节长度
	 * @return 格式化好的字节数组
	 */
	public static void formatString(String value, int fmtlen, byte[] dest,
			int destoff) throws Exception {
		System.arraycopy(formatString(value, fmtlen, ' '), 0, dest, destoff,
				fmtlen);
	}

	/**
	 * 格式化指定的串按指定的长度--左补特定字符
	 * 
	 * @param value
	 *            待格式化的字符串
	 * @param fmtlen
	 *            格式化字节长度
	 * @param fill
	 *            填充的字符
	 * @return 格式化好的字节数组
	 */
	public static byte[] formatStringLeftAlign(String value, int fmtlen,
			char fill) throws Exception {
		byte[] buff = new byte[fmtlen];
		byte[] fmt = value.getBytes(CHINESE_ENCODING);

		// 判断长度是否足够
		if (fmt.length > fmtlen)
			throw new Exception("format " + value + "," + fmtlen + " error!");

		// 初始化为最左部分为fill
		for (int i = 0; i < fmtlen - fmt.length; i++)
			buff[i] = (byte) fill;

		// 拷入
		if (fmt.length < fmtlen)
			System.arraycopy(fmt, 0, buff, fmtlen - fmt.length, fmt.length);
		else
			return (fmt);

		return (buff);
	}

	/**
	 * 以右补空格的方式格式化指定的double值按指定的长度
	 * 
	 * @param value
	 *            双精度数
	 * @param fmtlen
	 *            格式化字节长度
	 * @return 格式化好的字节数组
	 */
	public static byte[] formatDouble(double value, int fmtlen)
			throws Exception {
		return formatString(new DecimalFormat(DEFAULT_DECIMAL_FMT)
				.format(value), fmtlen);
	}

	/**
	 * 以左补0的方式格式化小数
	 * 
	 * @param value
	 *            双精度数
	 * @param fmtlen
	 *            格式化字节长度
	 * @return 格式化好的字节数组
	 */
	public static byte[] formatDoubleLeaderZero(double value, int fmtlen)
			throws Exception {
		return formatStringLeftAlign(new DecimalFormat(DEFAULT_DECIMAL_FMT)
				.format(value), fmtlen, '0');
	}

	/**
	 * 以右补空格的方式格式化指定的int值按指定的长度
	 * 
	 * @param value
	 *            整数
	 * @param fmtlen
	 *            格式化字节长度
	 * @return 格式化好的字节数组
	 */
	public static byte[] formatInteger(int value, int fmtlen) throws Exception {
		return formatString(new DecimalFormat(DEFAULT_INTEGER_FMT)
				.format((long) value), fmtlen);
	}

	/**
	 * 以右补空格的方式格式化指定的int值按指定的长度
	 * 
	 * @param value
	 *            整数
	 * @param fmtlen
	 *            格式化字节长度
	 * @return 格式化好的字节数组
	 */
	public static void formatLong(long value, int fmtlen, byte[] dest,
			int destoff) throws Exception {
		System.arraycopy(formatString(new DecimalFormat(DEFAULT_INTEGER_FMT)
				.format(value), fmtlen), 0, dest, destoff, fmtlen);
	}

	/**
	 * 按yyyyMMdd格式格式化日期
	 * 
	 * @return yyyyMMdd
	 */
	public static String getPackedYMDString(Date val) {
		return new SimpleDateFormat(PACKED_DATE_YMD_FMT).format(val);
	}

	/**
	 * 按yyyy-MM-dd格式格式化日期
	 * 
	 * @param val
	 * @return
	 */
	public static String getPackedYMDString2(Date val) {
		if (val == null) {
			return new SimpleDateFormat(DEFAULT_DATE_YMD_FMT)
					.format(new Date());
		}
		return new SimpleDateFormat(DEFAULT_DATE_YMD_FMT).format(val);
	}

	public static Date getShortDateFromLongDate(Date val) {
		try {
			return new SimpleDateFormat(DEFAULT_DATE_YMD_FMT)
					.parse(new SimpleDateFormat(DEFAULT_DATE_YMD_FMT)
							.format(val));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 以左补0的方式格式化整数
	 * 
	 * @param value
	 *            整数
	 * @param fmtlen
	 *            格式化字节长度
	 * @return 格式化好的字节数组
	 */
	public static byte[] formatIntegerLeaderZero(int value, int fmtlen)
			throws Exception {
		return formatStringLeftAlign(new DecimalFormat(DEFAULT_INTEGER_FMT)
				.format((long) value), fmtlen, '0');
	}

	/**
	 * 以左补0的方式格式化整数
	 * 
	 * @param value
	 *            整数
	 * @param fmtlen
	 *            格式化字节长度
	 * @param dest
	 *            目标数组
	 * @param destoff
	 *            目标数组起始位置
	 * @return 格式化好的字节数组
	 */
	public static void formatIntegerLeaderZero(int value, int fmtlen,
			byte[] dest, int destoff) throws Exception {
		System.arraycopy(formatStringLeftAlign(new DecimalFormat(
				DEFAULT_INTEGER_FMT).format((long) value), fmtlen, '0'), 0,
				dest, destoff, fmtlen);
	}

	/**
	 * 以缺省格式解析日期时间对象
	 * 
	 * @param 日期时间对象字符串
	 * @return 日期对象
	 */
	public static Date parseDateTime(String str) throws Exception {
		return new SimpleDateFormat(DEFAULT_DATE_FMT).parse(str);
	}

	/**
	 * 以YYYY-MM-DD格式解析日期时间对象
	 * 
	 * @param 日期时间对象字符串
	 * @return 日期对象
	 */
	public static Date parseYMDDateTime(String str) throws Exception {
		return new SimpleDateFormat(DEFAULT_DATE_YMD_FMT).parse(str);
	}

	/**
	 * 以yyyyMMdd格式解析日期时间对象
	 * 
	 * @param 日期时间对象字符串
	 * @return 日期对象
	 */
	public static Date parsePackedYMDDateTime(byte[] inbuf, int off, int len)
			throws Exception {
		String str = parseString(inbuf, off, len);
		return new SimpleDateFormat(PACKED_DATE_YMD_FMT).parse(str);
	}

	/**
	 * 以yyyyMMdd格式解析日期时间对象
	 * 
	 * @param 日期时间对象字符串
	 * @return 日期对象
	 */
	public static Date parsePackedYMDDateTime(String str) throws Exception {
		return new SimpleDateFormat(PACKED_DATE_YMD_FMT).parse(str);
	}

	/**
	 * 以缺省格式格式化日期为字节数组
	 * 
	 * @param dt
	 *            待格式化的日期对象
	 * @param fmtlen
	 *            格式化字节长度
	 * @return 格式化好的字节数组
	 */
	public static byte[] formatDateTime(Date dt, int fmtlen) throws Exception {
		return formatString(new SimpleDateFormat(DEFAULT_DATE_FMT).format(dt),
				fmtlen);
	}

	/**
	 * 检查一个字节数组,从start -- start + len是否全部为ascii数字
	 * 
	 * @param buff
	 *            字节数组
	 * @param start
	 *            起始下标
	 * @param len
	 *            长度
	 * @return 如果全部为数字则返回true,否则返回false
	 */
	public static boolean isdigitarray(byte[] buff, int start, int len) {
		if (buff == null || start < 0 || len <= 0 || start + len > buff.length)
			return (false);

		for (int ndx = start; ndx < start + len; ndx++)
			if (buff[ndx] < (byte) '0' || buff[ndx] > (byte) '9')
				return (false);

		return (true);
	}

	/**
	 * 以缺省格式解析字符串对象
	 * 
	 * @param inbuf
	 *            输入的字节数组
	 * @param off
	 *            开始解析的偏移量
	 * @param len
	 *            解析的长度
	 * @return 字符串对象
	 */
	public static String parseString(byte[] inbuf, int off, int len)
			throws Exception {
		return new String(inbuf, off, len, CHINESE_ENCODING).trim();
	}

	/**
	 * 以缺省格式解析字符串对象,如果长度为0,解析为NULL
	 * 
	 * @param inbuf
	 *            输入的字节数组
	 * @param off
	 *            开始解析的偏移量
	 * @param len
	 *            解析的长度
	 * @return 字符串对象
	 */
	public static String parseStringOrNull(byte[] inbuf, int off, int len)
			throws Exception {
		if (len <= 0)
			return null;
		String str = new String(inbuf, off, len, CHINESE_ENCODING).trim();
		if (str.length() == 0)
			return null;
		return (str);
	}

	/**
	 * 以缺省格式解析整数对象
	 * 
	 * @param inbuf
	 *            输入的字节数组
	 * @param off
	 *            开始解析的偏移量
	 * @param len
	 *            解析的长度
	 * @return 整数值
	 */
	public static int parseInteger(byte[] inbuf, int off, int len)
			throws Exception {
		String str = parseString(inbuf, off, len);
		if (str.length() == 0)
			return 0;
		// 将字符串转换为整数
		return Integer.parseInt(str);
	}

	/**
	 * 判断字符串是否为空(NULL or length == 0)
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isEmpty(String str) {
		return (str == null || str.trim().length() == 0);
	}

	/**
	 * 判断是否为全为数字
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNumeric(String str) {
		for (int i = 0; i < str.length(); i++) {
			if (!Character.isDigit(str.charAt(i))) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 以缺省格式解析整数对象
	 * 
	 * @param inbuf
	 *            输入的字节数组
	 * @param off
	 *            开始解析的偏移量
	 * @param len
	 *            解析的长度
	 * @return 整数值
	 */
	public static long parseLong(byte[] inbuf, int off, int len)
			throws Exception {
		String str = parseString(inbuf, off, len);
		if (str.length() == 0)
			return 0;
		// 将字符串转换为整数
		return Long.parseLong(str);
	}

	/**
	 * 以缺省格式解析数字对象
	 * 
	 * @param inbuf
	 *            输入的字节数组
	 * @param off
	 *            开始解析的偏移量
	 * @param len
	 *            解析的长度
	 * @return 整数值
	 */
	public static java.math.BigDecimal parseDecimal(byte[] inbuf, int off,
			int len) throws Exception {
		String str = parseString(inbuf, off, len);
		if (str.length() == 0)
			return java.math.BigDecimal.ZERO;
		// 将字符串转换为BigDecimal
		return java.math.BigDecimal.valueOf(Double.parseDouble(str));
	}

	/**
	 * 从全路径文件名中解析出不包含路径的文件名
	 * 
	 * @param path
	 *            全路径文件名
	 * @return 文件名
	 */
	public static String getFileName(String path) {
		String filename = path;
		// 取出最后一个路径分隔符的位置
		int pos = path.lastIndexOf(File.separator);
		if (pos >= 0)
			filename = path.substring(pos + 1);
		if (filename == null || filename.length() == 0)
			filename = null;

		return (filename);
	}

	/**
	 * 从全路径文件名中仅解析出文件名称--注意不包括路径名及扩展名
	 * 
	 * @param path
	 *            全路径文件名
	 * @return 不含扩展名的文件名
	 */
	public static String getFileReallyName(String path) {
		String filename = getFileName(path);
		if (filename == null)
			return (null);

		int pos = filename.lastIndexOf(".");
		if (pos > 0)
			filename = filename.substring(0, pos);

		if (filename == null || filename.length() == 0)
			filename = null;

		return (filename);
	}

	/**
	 * 确保读取指定字节的数据
	 * 
	 * @param is
	 *            网络输入流
	 * @param buff
	 *            存储的字节数组
	 * @param off
	 *            起始偏移量
	 * @param len
	 *            网络读取的长度
	 * @return 读取成功时返回true,否则返回false
	 */
	private static boolean getData(InputStream is, byte[] buff, int off, int len)
			throws Exception {
		int left = len;
		int nbytes, nreads = 0;

		while (left > 0) {
			nbytes = is.read(buff, off, left);
			if (nbytes < 0)
				break;
			nreads += nbytes;
			off += nbytes;
			left -= nbytes;
		}

		// TPMLogger.debug( "network read return " + nreads + "bytes [" + new
		// String( buff, orig_off, nreads,TPMUtil.CHINESE_ENCODING ) + "]." );
		return (left == 0);
	}

	/**
	 * 获取指定长度的网络报文,并设置读超时
	 * 
	 * @param sckconn
	 *            网络连接socket
	 * @param is
	 *            网络连接输入流
	 * @param len
	 *            要读取的字节长度
	 * @param timeout
	 *            超时时间(毫秒)
	 * @return 成功读取的字节数组
	 */
	public static byte[] getData(Socket sckconn, InputStream is, int len,
			int timeout) {
		byte[] buff = new byte[len];
		try {
			// 先设置超时时间
			if (timeout > 0)
				sckconn.setSoTimeout(timeout);
			if (!getData(is, buff, 0, len)) {
				// TPMLogger.info("read network data error!");
				buff = null;
			}
			if (timeout > 0)
				sckconn.setSoTimeout(0);
		} catch (Exception ex_) {
			buff = null;
			// TPMLogger.error( ex_ );
		} finally {
			// System.out.print("");
		}

		return buff;
	}

	/**
	 * 检索某目录下的特定文件类型的文件名
	 * 
	 * @param path
	 *            目录名
	 * @param type
	 *            文件扩展名
	 * @return 以';'分隔的文件名列表
	 */
	public static String getFileNameListByType(String path, String type) {
		File[] ffs = new File(path).listFiles();
		String buff = "";
		for (int i = 0; i < ffs.length; i++) {
			String name = ffs[i].getName().toUpperCase();
			if (ffs[i].isFile() && name.endsWith(type.toUpperCase())) {
				if (buff.length() > 0)
					buff = buff + ";" + ffs[i].getName();
				else
					buff = ffs[i].getName();
			}
		}
		return (buff);
	}

	public static final String PCPSCONTEXT = "PCPSCONTEXT";

	/**
	 * 设置日志路径
	 */
	private static void setLogEntry(String logpath) {
		try {
			WorkContextMap map = (WorkContextMap) new InitialContext()
					.lookup("java:comp/WorkContextMap");
			// 日志路径
			WorkContext stringContext = PrimitiveContextFactory.create(logpath);
			map.put(PCPSCONTEXT, stringContext, PropagationMode.GLOBAL);
		} catch (Exception e) {
		}
	}

	/**
	 * 设置tuxedo交易总入口日志
	 */
	public static void setTuxedoLogEntry() {
		setLogEntry("tuxedo");
	}

	/**
	 * 设置webservice交易总入口日志
	 */
	public static void setWebserviceLogEntry(String path) {
		setLogEntry("webservice/" + path);
	}

	/**
	 * 设置dayoff交易总入口日志
	 */
	public static void setDayOffLogEntry(String issueCompanyNo) {
		setLogEntry("dayoff/" + issueCompanyNo);
	}

	/**
	 * 设置tuxedo商户交易入口日志(按商户/POS(可选)/交易码)
	 */
	public static void setMrchLogEntry(String mrchno, String posno,
			String trancode) {
		if (isEmpty(posno))
			setLogEntry("tuxedo" + "/" + mrchno + "/" + trancode);
		else
			setLogEntry("tuxedo" + "/" + mrchno + "/" + posno + "/" + trancode);
	}

	/**
	 * 按照时间戳的取法YYYYMMDDHHmmSSsss生成唯一文件名
	 * 
	 * @return 返回唯一的文件名
	 */
	public static String getUniqueFileName() {
		return new SimpleDateFormat(DEFAULT_TIMESTAMP_FMT).format(new Date());
	}

	public static void Log(String msg) {
		myLogger.info(msg);
	}

	public static void Log(String msg, Throwable e) {
		myLogger.warning(msg, e);
	}

	public static void Log(Throwable e) {
		myLogger.warning("", e);
	}

	/**
	 * 生成字符串的取值范围
	 * 
	 * 柯锋利使用
	 */
	private static char ch[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
			'9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
			'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
			'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
			'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
			'z', '0', '1' };// 最后又重复两个0和1，因为需要凑足数组长度为64

	private static Random random = new Random();

	/**
	 * 生成指定长度的随机字符串
	 * 
	 * @param length
	 * @return 随机字符串
	 */
	public static String createRandomString(int length) {
		if (length > 0) {
			int index = 0;
			char[] temp = new char[length];
			int num = random.nextInt();
			for (int i = 0; i < length % 5; i++) {
				temp[index++] = ch[num & 63];// 取后面六位，记得对应的二进制是以补码形式存在的。
				num >>= 6;// 63的二进制为:111111
				// 为什么要右移6位？因为数组里面一共有64个有效字符。为什么要除5取余？因为一个int型要用4个字节表示，也就是32位。
			}
			for (int i = 0; i < length / 5; i++) {
				num = random.nextInt();
				for (int j = 0; j < 5; j++) {
					temp[index++] = ch[num & 63];
					num >>= 6;
				}
			}
			return new String(temp, 0, length);
		} else if (length == 0) {
			return "";
		} else {
			throw new IllegalArgumentException();
		}
	}

	/**
	 * 发送邮件
	 * 
	 * 柯锋利
	 * 
	 * @param host
	 *            host = "smtp.163.com"; // 邮件服务器
	 * @param username
	 *            username = "kx_80"; // 发送邮件用户名
	 * @param password
	 *            password = "1980113"; // 发送邮件密码
	 * @param sendtext
	 *            sendtext = "中国人民万岁"; // 邮件内容
	 * @param toAddr
	 *            toAddr = "kx_80@163.com"; // 接收邮件地址
	 * @param fromAddr
	 *            fromAddr = "kx_80@163.com"; // 发送邮件地址
	 * @param title
	 *            title = "测试"; // 邮件标题
	 * @throws Exception
	 */
	// public static void sendMail(String host, String username, String
	// password,
	// String sendtext, String toAddr, String fromAddr, String title)
	// throws Exception {
	//
	// Properties props = new Properties();// 创建属性对象
	// props.put("mail.smtp.host", host);// 设置smtp服务器地址
	// props.put("mail.smtp.auth", "true");// 设置服务器smtp需要验证
	// Session session = Session.getInstance(props, null);// 创建新邮件并群发
	// // Session session = Session.getDefaultInstance(props);
	// // session.setDebug(true);
	// MimeMessage message = new MimeMessage(session);// 创建过程对象
	// message.setFrom(new InternetAddress(fromAddr));
	//
	// message.addRecipient(Message.RecipientType.TO, new InternetAddress(
	// toAddr));
	// message.setSubject(title);// 设置主题
	// Multipart multipart = new MimeMultipart();
	// BodyPart contentPart = new MimeBodyPart();
	// contentPart.setContent(sendtext, "text/html;charset=GBK");// 设置信件内容
	// multipart.addBodyPart(contentPart);
	// message.setContent(multipart);
	// message.saveChanges();
	// Transport transport = session.getTransport("smtp");
	// transport.connect(host, username, password);
	// transport.sendMessage(message, message.getAllRecipients());
	// transport.close();
	// }
	/**
	 * 检查是否超过锁定时限
	 * 
	 * @param sysTime
	 *            系统时间
	 * @param pwdErrCnt
	 *            密码错误次数
	 * @param tradTime
	 *            上次错误时间
	 * @param maxPwdErrCnt
	 *            最大允许错误次数
	 * @param pwdErrLimit
	 *            密码错锁定时限
	 * @return true - 锁定 false - 未锁定
	 */
	public static boolean isCardLocked(java.util.Date sysTime,
			Integer pwdErrCnt, java.util.Date lastPwdErrTime,
			Integer maxPwdErrCnt, Integer pwdErrLimit) {
		// 如果上次密码错误时间未设
		if (lastPwdErrTime == null)
			return (false);
		// 检查卡是否被锁定
		java.util.Calendar cal = java.util.Calendar.getInstance();
		cal.setTime(lastPwdErrTime);
		cal.add(java.util.Calendar.HOUR_OF_DAY, pwdErrLimit);
		java.util.Date unlockTime = cal.getTime();
		return (pwdErrCnt.compareTo(maxPwdErrCnt) >= 0 && unlockTime
				.compareTo(sysTime) > 0);
	}

	/**
	 * 无顺序去重复 List order not maintained *
	 */
	@SuppressWarnings("unchecked")
	public static List removeDuplicate(List arlList) {
		HashSet h = new HashSet(arlList);
		arlList.clear();
		arlList.addAll(h);
		return arlList;
	}

	/**
	 * 有顺序去重复 List order maintained *
	 */
	@SuppressWarnings("unchecked")
	public static List removeDuplicateWithOrder(List arlList) {
		Set set = new HashSet();
		List newList = new ArrayList();
		for (Iterator iter = arlList.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (set.add(element))
				newList.add(element);
		}
		arlList.clear();
		arlList.addAll(newList);
		return arlList;
	}

	/**
	 * 字符串转换成十六进制值
	 * 
	 * @param bin
	 *            String 我们看到的要转换成十六进制的字符串
	 * @return
	 */
	public static String bin2hex(String bin) {
		char[] digital = "0123456789ABCDEF".toCharArray();
		StringBuffer sb = new StringBuffer("");
		byte[] bs = bin.getBytes();
		int bit;
		for (int i = 0; i < bs.length; i++) {
			bit = (bs[i] & 0x0f0) >> 4;
			sb.append(digital[bit]);
			bit = bs[i] & 0x0f;
			sb.append(digital[bit]);
		}
		return sb.toString();
	}

	/**
	 * 十六进制转换字符串
	 * 
	 * @param hex
	 *            String 十六进制
	 * @return String 转换后的字符串
	 */
	public static String hex2bin(String hex) {
		String digital = "0123456789ABCDEF";
		char[] hex2char = hex.toCharArray();
		byte[] bytes = new byte[hex.length() / 2];
		int temp;
		for (int i = 0; i < bytes.length; i++) {
			temp = digital.indexOf(hex2char[2 * i]) * 16;
			temp += digital.indexOf(hex2char[2 * i + 1]);
			bytes[i] = (byte) (temp & 0xff);
		}
		return new String(bytes);
	}

	/**
	 * zxp
	 * 
	 * @param str
	 *            交易时16进制截取空格
	 * @return
	 */
	public static String subStringParseString(String str) {
		if (str.length() < 1) {
			return null;
		}
		String hexStr = bin2hex(str);
		int indexs = hexStr.indexOf("20");// 空格16进制为20
		if (indexs > -1) {
			String resStr = hexStr.substring(0, indexs);
			String tarStr = hex2bin(resStr);
			if (tarStr.length() < 1) {
				return null;
			} else {
				return tarStr;
			}
		}
		return str;
	}

	private static final String DATE_FORMAT_YMD = "yyyy-MM-dd";
	private static final String DATE_FORMAT_YMDHMS = "yyyy-MM-dd HH:mm:ss";
	private static final String DATE_FORMAT_YMDHMS_PACKED = "yyyyMMddHHmmss";

	/**
	 * 使用构造函数获取webservice中使用XMLGregorianCalendar类型时间
	 * 
	 * @param java
	 *            .util.date
	 * @return XMLGregorianCalendar时间
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public static XMLGregorianCalendar getXMLGregorianCalendar(Date date)
			throws Exception {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		DatatypeFactory dtf = DatatypeFactory.newInstance();
		return dtf.newXMLGregorianCalendar(calendar.get(calendar.YEAR),
				calendar.get(calendar.MONTH) + 1, calendar
						.get(calendar.DAY_OF_MONTH), calendar
						.get(calendar.HOUR_OF_DAY), calendar
						.get(calendar.MINUTE), calendar.get(calendar.SECOND),
				calendar.get(calendar.MILLISECOND), calendar
						.get(calendar.ZONE_OFFSET)
						/ (1000 * 60));
	}

	/**
	 * 使用set赋值获取webservice中使用XMLGregorianCalendar类型时间，
	 * 
	 * @param date
	 *            年月日时分秒
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public static XMLGregorianCalendar getXMLGregorianCalendarByDate(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int year = calendar.get(calendar.YEAR);
		int month = calendar.get(calendar.MONTH) + 1;
		int day = calendar.get(calendar.DAY_OF_MONTH);
		int hour = calendar.get(calendar.HOUR_OF_DAY);
		int minute = calendar.get(calendar.MINUTE);
		int second = calendar.get(calendar.SECOND);
		DatatypeFactory dtf = null;
		try {
			dtf = DatatypeFactory.newInstance();
		} catch (DatatypeConfigurationException e) {
			e.printStackTrace();
		}
		XMLGregorianCalendar xmlgcl = dtf.newXMLGregorianCalendar();
		xmlgcl.setYear(year);
		xmlgcl.setMonth(month);
		xmlgcl.setDay(day);
		xmlgcl.setHour(hour);
		xmlgcl.setMinute(minute);
		xmlgcl.setSecond(second);
		return xmlgcl;
	}

	/**
	 * 字符串转化为Date类型,时间转化错误返回null
	 * 
	 * @param time
	 * @return
	 */
	public static Date getDateByString(String time) {
		SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMDHMS);
		Date date = null;
		try {
			date = sdf.parse(time);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return date;
	}

	/**
	 * 字符串转化为Date类型,时间转化错误返回null
	 * 
	 * @param time
	 * @return
	 */
	public static Date getDateYMDByString(String time) {
		SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMD);
		Date date = null;
		try {
			date = sdf.parse(time);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return date;
	}

	/**
	 * XMLGregorianCalendar时间类型转化为String类型
	 * 
	 * @param xmlgc
	 * @return
	 */
	public static String getStringByXMLGregorianCalendar(
			XMLGregorianCalendar xmlgc) {
		GregorianCalendar gcl = xmlgc.toGregorianCalendar();
		SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT_YMDHMS);
		String date = formatter.format(gcl.getTime());
		return date;
	}

	/**
	 * 去掉时间的HMS部分只返回日期部分
	 * 
	 * @param idate
	 * @return
	 */
	public static Date getZeroedHMS(Date idate) {
		if (idate == null)
			return idate;
		// 去掉记帐日期的时分秒部分
		java.util.Calendar cal = java.util.Calendar.getInstance();
		cal.setTime(idate);
		cal.set(java.util.Calendar.HOUR_OF_DAY, 0);
		cal.set(java.util.Calendar.MINUTE, 0);
		cal.set(java.util.Calendar.SECOND, 0);
		return cal.getTime();
	}

	/**
	 * 将标准时间转化为YYYY-MM-DD
	 * 
	 * @param date
	 * @return
	 */
	public static String getStringYMDByDate(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMD);
		String result = sdf.format(date);
		return result;
	}

	public static String getStringYMDByDate(Date date, String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		String result = sdf.format(date);
		return result;
	}

	public static Date getDateFormat(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMD);
		String result = sdf.format(date);
		Date d = null;
		try {
			d = sdf.parse(result);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return d;
	}

	/**
	 * 计算对象数组的hashCode
	 * 
	 * @param objlist
	 * @return
	 */
	public static int getObjectListHashCode(Object[] objlist) {
		int result = 13;

		if (objlist == null)
			return result;

		for (int i = 0; i < objlist.length; i++) {
			result = 37 * result
					+ (objlist[i] == null ? 11 : objlist[i].hashCode());
		}
		return result;
	}

	/**
	 * 将标准时间转化为YYYYMMDDHHMISS
	 * 
	 * @param date
	 * @return
	 */
	public static String getStringYMDHMSPackedByDate(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMDHMS_PACKED);
		String result = sdf.format(date);
		return result;
	}

	/**
	 * 自写sql取出的BigDecime转BigInteger
	 * 
	 * @param date
	 * @return
	 */
	public static BigInteger BigDecimalToBigInteger(Object b) {
		String s = "0";
		try {
			s = String.valueOf(((BigDecimal) b).intValue());
		} catch (Exception e) {
			// TODO: handle exception
			return null;
		}
		return (new BigInteger(s));
	}

	/**
	 * 比较两个对象是否相等,用于复合主键中字段的比较
	 * 
	 * @param obj1
	 * @param obj2
	 * @return
	 */
	public static boolean compareObject(Object obj1, Object obj2) {
		if (obj1 == obj2)
			return true;
		else if (obj1 == null && obj2 != null)
			return false;
		else if (obj1 != null && obj2 == null)
			return false;
		return obj1.equals(obj2);
	}

	/**
	 * 查询时选择查询当前选中机构还是下级所有机构
	 * 
	 * @param webInput
	 *            登录用户归属
	 * @param branchNo
	 *            机构号
	 * @param colName
	 *            查询列
	 * @return
	 */
	public static String getSqlCond(PCPSWebInput webInput, String branchNo,
			String colName) {
		// 用户归属机构号为空时不查询数据
		if (PCPSUtil.isEmpty(webInput.getOperBranchNo())) {
			return " and 1!=1";
		}
		// 首次点菜单时branchNo
		if (PCPSUtil.isEmpty(branchNo)) {
			branchNo = webInput.getOperBranchNo();
		}
		String sql = "";
		if (!webInput.isAll()) {
			sql = " and "
					+ colName
					+ " in (select subBranchNo from sysbranchsubord t where t.branchno='"
					+ branchNo + "')";
		} else {
			sql = " and " + colName + " ='" + branchNo + "'";
		}
		return sql;
	}

	public static String getSqlCondType(PCPSWebInput webInput, String branchNo,
			String colName, String type) {
		// 用户归属机构号为空时不查询数据
		if (PCPSUtil.isEmpty(webInput.getOperBranchNo())) {
			return " and 1!=1";
		}
		// 首次点菜单时branchNo
		if (PCPSUtil.isEmpty(branchNo)) {
			branchNo = webInput.getOperBranchNo();
		}
		String sql = "";
		if (!webInput.isAll()) {
			sql = " and "
					+ colName
					+ " in (select subBranchNo from sysbranchsubord t where t.branchno='"
					+ branchNo + "' and SubBranchType='" + type + "')";
		} else {
			sql = " and " + colName + " ='" + branchNo + "'";
		}
		return sql;
	}

	/**
	 * 辨别机构身份
	 * 
	 * @param 机构编号
	 * @return 机构身份枚举
	 */
	public static Integer branchDistinguish(String sysbranchno) {
		// 长度为6是发卡商
		if (sysbranchno.length() == 6)
			return PCPSUtil.SysBranch_IssueCompany;
		else if (sysbranchno.substring(6, 7).equals("8")) {
			// 第7位是8则是商户或商户机构，进一步判断
			if (sysbranchno.length() == 14)
				return PCPSUtil.SysBranch_Merchant;
			else
				return PCPSUtil.SysBranch_MerchantBranch;
		} else if (sysbranchno.substring(6, 8).equals("99")) {
			// 第78位是99则是发卡商机构
			return PCPSUtil.SysBranch_IssueBranch;
		} else if (sysbranchno.substring(6, 8).equals("98")) {
			// 第78位是98则是销售商或销售机构，进一步判断
			if (sysbranchno.length() == 14)
				return PCPSUtil.SysBranch_SaleCompany;
			else
				return PCPSUtil.SysBranch_SaleBranch;
		}
		return PCPSUtil.SysBranch_INVALID;
	}

	/**
	 * 限制取小
	 * 
	 * @param lim
	 * @param newLim
	 * @return
	 */
	public static BigInteger setValidateLimit(BigInteger lim, BigInteger newLim) {
		// 如果新限制 < 0,则原限制不变
		int result = newLim.compareTo(BigInteger.ZERO);
		if (result < 0)
			return lim;
		// 如果新限制 = 0,则返回新限制
		if (result == 0)
			return newLim;
		// 如果原限制<0,则返回新限制
		if (lim.compareTo(BigInteger.ZERO) < 0)
			return newLim;
		// 如果原限制>0,且新限制 <原限制,则返回新限制
		if (lim.compareTo(BigInteger.ZERO) > 0) {
			if (newLim.compareTo(lim) < 0)
				return newLim;
		}
		// 否则返回原限制
		return lim;
	}

	/**
	 * 新增修改数据库日志记录 只记录属性不为NULL日志
	 * 
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	// String lastFieldName
	@SuppressWarnings("unchecked")
	public static String RecordingOperationLog(Object obj, String lastFieldName) {
		StringBuffer resultStr = new StringBuffer();
		// 静态公有属性,getPcInheritedFieldCount()
		Hashtable publicFields = new Hashtable();
		Field[] existFields = obj.getClass().getFields();
		for (int i = 0; i < existFields.length; i++) {
			publicFields.put(existFields[i].getName(), "exist");
		}
		// 所有属性
		Field[] fields = obj.getClass().getDeclaredFields();
		Class classType = obj.getClass();
		String claName = classType.getName();
		resultStr.append("表["
				+ claName.substring(claName.lastIndexOf('.') + 1, claName
						.length()) + "]");
		String fieldName = null;
		String firstLetter = null;
		String getMethodName = null;
		Method getMethod = null;
		Object value = null;
		int lastFieldPostion = 0;
		// 获得最后一个属性位置
		for (int i = 0; i < fields.length; i++) {
			fieldName = fields[i].getName();
			// 过滤出所有静态公有属性,例如 public static final String
			// ISSUECOMPANY_NORMAL_ENDDAY = "1";
			if (publicFields.get(fieldName) == null) {
				// 根据对象最后一个属性过滤掉其他别的异常方法,例如pcInheritedFieldCount,serialVersionUID
				if (fieldName.equals(lastFieldName)) {
					lastFieldPostion = i;
				}
			}
		}
		// 反射获取值
		for (int i = 0; i < fields.length; i++) {
			fieldName = fields[i].getName();
			if (publicFields.get(fieldName) == null) {
				if (i < lastFieldPostion + 1) {
					firstLetter = fieldName.substring(0, 1).toUpperCase();
					getMethodName = "get" + firstLetter
							+ fieldName.substring(1);
					try {
						getMethod = classType.getMethod(getMethodName,
								new Class[] {});
						value = getMethod.invoke(obj, new Object[] {});
						if (value != null) {
							if (!PCPSUtil.isEmpty(value.toString())) {
								resultStr.append(fieldName + "：" + value + ",");
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
						continue;
					}
				}
			}
		}
		return resultStr.toString();
	}

	/**
	 * 获取6位随即数
	 */
	public static String getRandom(Integer length) {
		// length表示生成字符串的长度
		String base = "abcdefghijklmnopqrstuvwxyz0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}

	/**
	 * 获取随即长度字符串
	 */
	public static String getRandomString(Integer length) {
		// length表示生成字符串的长度
		String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ0123456789_";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}

	/** ** 16进制实用方法 *** */

	private static final char _hexcodes[] = { '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

	/**
	 * 取字节串
	 * 
	 * @param val
	 * @return
	 */
	public static final String getByteHexString(int val) {
		StringBuilder sb = new StringBuilder();
		sb.append(_hexcodes[(val >> 4) & 0x0F]);
		sb.append(_hexcodes[val & 0x0F]);
		return sb.toString();
	}

	public static final String getHexString(byte[] bval) {
		StringBuilder sb = new StringBuilder();
		for (byte c : bval)
			sb.append(getByteHexString((int) c));
		return sb.toString();
	}

	public static final String getHexString(byte[] bval, int off, int len) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < len; i++)
			sb.append(getByteHexString((int) bval[off + i]));
		return sb.toString();
	}

	/**
	 * 返回32位整数的16进制字符串
	 * 
	 * @param ival
	 * @return
	 */
	public static final String getHexIntegerString(int ival) {
		byte[] bv = new byte[4];
		bv[0] = (byte) ((ival >> 24) & 0x00FF);
		bv[1] = (byte) ((ival >> 16) & 0x00FF);
		bv[2] = (byte) ((ival >> 8) & 0x00FF);
		bv[3] = (byte) (ival & 0x00FF);
		return getHexString(bv, 0, 4);
	}

	public static final byte[] getBytes(String hex) {
		String digital = "0123456789ABCDEF";
		char[] hex2char = hex.toUpperCase().toCharArray();
		byte[] rb = new byte[hex.length() / 2];
		int temp;
		for (int i = 0; i < rb.length; i++) {
			temp = digital.indexOf(hex2char[2 * i]) * 16;
			temp += digital.indexOf(hex2char[2 * i + 1]);
			rb[i] = (byte) (temp & 0xff);
		}
		return rb;
	}

	/**
	 * 从字节数组指定位置开始,按高位在前(网络字节序)的顺序解析整数
	 * 
	 * @param bval
	 * @param off
	 * @param len
	 * @return
	 */
	public static final int parseNetworkInteger(byte[] bval, int off, int len) {
		if (bval == null || off < 0 || off + len > bval.length)
			return (-1);
		int ival = 0;
		for (int i = 0; i < len; i++) {
			ival = (ival << 8);
			ival += bval[off + i];
		}
		return ival;
	}

	/**
	 * 将指定字符串以ASC方式编码为16进制字符串
	 * 
	 * @param sval
	 * @param len
	 * @return
	 */
	public static final String encodeAscToHexString(String sval, int len) {
		try {
			if (PCPSUtil.isEmpty(sval))
				sval = "";
			byte[] bval = sval.getBytes(CHINESE_ENCODING);
			byte[] rval = new byte[len];
			for (int i = 0; i < len; i++) {
				if (i >= bval.length)
					break;
				rval[i] = bval[i];
			}
			return PCPSUtil.getHexString(rval);
		} catch (UnsupportedEncodingException e) {
			PCPSUtil.Log("invalid MSG[" + sval + "]", e);
		}
		return PCPSUtil.getHexString(new byte[len]);
	}

	public static final String decodeHexStringToAsc(String val) {
		byte[] shex = PCPSUtil.getBytes(val);
		try {
			return new String(shex, CHINESE_ENCODING);
		} catch (UnsupportedEncodingException e) {
			PCPSUtil.Log("invalid MSG[" + val + "]", e);
		}
		return "";
	}

	public static final String decodeHexStringToAsc(String sval, int off,
			int len) {
		return decodeHexStringToAsc(sval.substring(off, off + len));
	}

	/**
	 * 将数据库中amount分转换为前台以"元"为单位
	 * 
	 * @param fen
	 * @return
	 */
	public static String changeF2Y(String amount) throws Exception {
		if (amount == null) {
			return "";
		}
		if (!amount.matches("\\-?[0-9]+")) {
			throw new Exception("金额格式有误");
		}
		String y = BigDecimal.valueOf(Long.valueOf(amount)).divide(
				new BigDecimal(100)).toString();
		if (y.indexOf(".") > -1) {
			return y;
		} else {
			return y + ".00";
		}
	}

	/**
	 * 将前台输入的以元为单位的金额,转化成以分为单位
	 * 
	 * @param amount
	 * @return
	 */
	public static String changeY2F(String amount) {
		try {
			String currency = amount.replaceAll("\\$|\\￥|\\,", "");
			int index = currency.indexOf(".");
			int length = currency.length();
			Long amLong = 0l;
			if (index == -1) {
				amLong = Long.valueOf(currency + "00");
			} else if (length - index >= 3) {
				amLong = Long.valueOf((currency.substring(0, index + 3))
						.replace(".", ""));
			} else if (length - index == 2) {
				amLong = Long.valueOf((currency.substring(0, index + 2))
						.replace(".", "") + 0);
			} else {
				amLong = Long.valueOf((currency.substring(0, index + 1))
						.replace(".", "")
						+ "00");
			}
			return amLong.toString();
		} catch (Exception e) {
			PCPSUtil.Log("金额元转分[" + amount + "]", e);
		}
		return "0";
	}

	public static String getLikeString(String pattern) {
		if (PCPSUtil.isEmpty(pattern))
			pattern = "";
		if (!pattern.startsWith("%"))
			pattern = "%" + pattern;
		if (!pattern.endsWith("%"))
			pattern = pattern + "%";
		return pattern;
	}

	/**
	 * 去除字符串中的空格、回车、换行符、制表符
	 * 
	 * @param str
	 * @return
	 */
	public static String replaceBlank(String str) {
		String dest = "";
		if (str != null) {
			Pattern p = Pattern.compile("\\s*|\t|\r|\n");
			Matcher m = p.matcher(str);
			dest = m.replaceAll("");
		}
		return dest;
	}

	/**
	 * 时间加天数得到时间
	 * 
	 * @param time
	 * @param daynum
	 * @return
	 */
	public static String getSubductionDays(String time, int daynum) {
		try {
			Date beginDate = new SimpleDateFormat(DEFAULT_DATE_YMD_FMT)
					.parse(time);
			Calendar date = Calendar.getInstance();
			date.setTime(beginDate);
			date.set(Calendar.DATE, date.get(Calendar.DATE) + daynum);
			return new SimpleDateFormat(DEFAULT_DATE_YMD_FMT).format(date
					.getTime());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 按四舍五入法计算费率
	 * 
	 * @param ratio
	 * @param amount
	 * @return ratio * amount / 10000
	 */
	public static BigInteger calcFee(BigInteger ratio, BigInteger amount) {
		BigInteger bi = new BigDecimal(ratio.abs()).multiply(
				new BigDecimal(amount.abs())).divide(
				BigDecimal.valueOf(10000.0), 0, RoundingMode.HALF_UP)
				.toBigInteger();
		if (ratio.signum() == amount.signum())
			return bi;
		return BigInteger.ZERO.subtract(bi);
	}

	/**
	 * 获取账务日期加天数后的日期
	 * 
	 * @param tranDate账务日期
	 * @param daynum负数表示时间之间
	 * @return
	 */
	public static Date getSubductionDays(Date tranDate, int daynum) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(tranDate);
		cal.add(Calendar.DATE, daynum);
		tranDate = cal.getTime();
		return tranDate;
	}

	public static String getIssueCompanyNo(PCPSWebInput webInput) {
		if (webInput == null || PCPSUtil.isEmpty(webInput.getOperBranchNo())) {
			return "";
		}
		return webInput.getOperBranchNo().substring(0, 6);
	}

	public static String getICNoByBranchNo(String saleBranchNo) {
		if (PCPSUtil.isEmpty(saleBranchNo)) {
			return "";
		}
		return saleBranchNo.substring(0, 6);
	}
}